/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.isd.pool.web;


import com.isd.global.modelo.CorreoElectronico;
import com.isd.global.modelo.Parametro;
import com.isd.global.rn.ParametrosRN;
import com.isd.global.util.JsfUtil;
import com.isd.global.util.SenderEmail;
import com.isd.global.web.MailFactory;
import com.isd.pool.modelo.EstadoPool;
import com.isd.pool.modelo.EstadoReserva;
import com.isd.pool.modelo.ItemPicking;
import com.isd.pool.modelo.ItemProductoPool;
import com.isd.pool.modelo.Pool;
import com.isd.pool.modelo.ReservasPool;
import com.isd.pool.modelo.TipoFinalizacion;
import com.isd.pool.rn.PoolRN;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ApplicationScoped;
import javax.ejb.EJB;


/**
 *
 * @author Claudio
 */
@ManagedBean
@ApplicationScoped
public class PoolAplicacionBean implements Serializable {

    @EJB private PoolRN poolRN;
    @EJB private ParametrosRN parametroRN;
    private List<Pool> pooles;
    private List<Pool> poolesRestringidos;

    //Correos para enviar si el pool no se cierra
    List<CorreoElectronico> correos;

    private Parametro p;
    
    @EJB private MailFactory mailFactoryBean;

    /** Creates a new instance of AplicacionBean */
    public PoolAplicacionBean(){
        
    }

    @PostConstruct
    private void init() {
        try {
            correos = new ArrayList<CorreoElectronico>();
            p = parametroRN.getParametros();
            actualizarDatos();
        } catch (Exception ex) {
            Logger.getLogger(PoolAplicacionBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void actualizarDatos(){
        
        try {

            pooles = poolRN.getVentasPublicasVisibles();
            poolesRestringidos = poolRN.getVentasRestringidasVisibles();

        } catch (Exception ex) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "actualizarDatos", ex);                        
        }
    }

    /**
     * Actualiza los datos de una venta especial seleccionada al cargar una reserva
     * @param pool
     */
    public synchronized void guardarDatosPool(Pool pool){

        try {
            sincronizarCantidades(pool);
            poolRN.guardar(pool);
            actualizarDatos();
        } catch (Exception e) {

            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "guardarDatosPool", e);            
            JsfUtil.addErrorMessage("Problemas para guardar datos: " + e.getMessage());            
        }
    }

    //@Schedule(hour = "*", minute = "*" , second = "15")
    public void actualizarPoolesNoCerrados(){
        
        try {
            List<Pool> poolesCerrar = poolRN.getVentasParaCerrar();

            if (poolesCerrar == null) {
                return;
            }

            for (Pool p : poolesCerrar) {

                if (p.getDisponibleHasta().before(new Date())) {

                    /**
                     * Marcamos como no cerradas las ventas que solo son exitosas
                     * cuando se consumen todas las cantidades disponibles, de lo
                     * contrario la venta es no exitosa
                     */
                    if (p.getCantidadDisponible().compareTo(BigDecimal.ZERO) == 1 &&
                            p.getTipo().getTipoFinalizacion().equals(TipoFinalizacion.SoloPorCantidad)) {

                        p.setFechaFin(p.getDisponibleHasta());
                        p.setEstado(EstadoPool.NoCerrado);

                        if (p.getReservas() != null) {

                            correos = new ArrayList<CorreoElectronico>();

                            for (ReservasPool r : p.getReservas()) {

                                if (!r.getEstado().equals(EstadoReserva.AnuladoCliente)) {
                                    r.setEstado(EstadoReserva.PoolNoCerrado);
                                    correos.add(generarCorreoElectronicoPoolNoCerradoCliente(r));
                                }
                            }
                        }
                        poolRN.guardar(p);

                        //Generamo el correo para la empresa
                        correos.add(generarCorreoResumenPoolEmpresa(p));
                        enviarNotificaciones();
                    }else{

                        p.setFechaFin(p.getDisponibleHasta());
                        p.setEstado(EstadoPool.Cerrado);
                        poolRN.guardar(p);
                    }

                }
            }
        } catch (Exception e) {

            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "actualizarPoolesNoCerrados", e);            
        }
    }
    
    public void sincronizarCantidades(Pool pool) throws Exception {

        if (pool.getTipo().getTipoFinalizacion()!=null ){
            if(pool.getTipo().getTipoFinalizacion().equals(TipoFinalizacion.SoloPorTiempo)){
                return;
            }
        }
        
        BigDecimal cantRes = poolRN.getCantidadReservadaByPool(pool.getNroPool(), EstadoReserva.Confirmado);
        
        for(ItemProductoPool ipp:pool.getProductos()){   
            
            BigDecimal reservasByProducto = poolRN.getCantidadReservadaByItemProductoPool(ipp).negate();
            int pickingByProducto = poolRN.getCantidadPickingByItemProductoPool(ipp);
            
//            System.err.println("cant picking: " + pickingByProducto);            
            ipp.setCantidadDisponible(ipp.getCantidadTotal().add(reservasByProducto).add(new BigDecimal(pickingByProducto).negate()));            
            
        }

        if(pool.getItemsPicking()!=null){
            for(ItemPicking ip: pool.getItemsPicking()){
                if(ip.getCantid()>0){
                    if(ip.getDebaja().equals("N")){
                        
                        cantRes = cantRes.add(new BigDecimal(ip.getCantid()));
                    }
                }
            }
        }
        
        pool.setCantidadDisponible(pool.getCantidadTotal().add(cantRes.negate()));
        
        //Si la cantidad es cero y el tipo finaliza por cantidad, cerramos el pool
        if(pool.getCantidadDisponible().compareTo(BigDecimal.ZERO)<=0){            

            pool.setFechaFin(new Date());
            pool.setEstado(EstadoPool.Cerrado); 
            poolRN.guardar(pool);
        }
        
        if(pool.getCantidadDisponible().compareTo(BigDecimal.ZERO)<0){
            pool.setCantidadDisponible(BigDecimal.ZERO);
            poolRN.guardar(pool);
        }            
    }

    public CorreoElectronico generarCorreoElectronicoPoolNoCerradoCliente(ReservasPool rs){

        SimpleDateFormat formateadorFechaHora = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

        CorreoElectronico ce = new CorreoElectronico();        
        String destinatario = "";

        if(p.getModoPrueba().equals("S")){
            destinatario = p.getRecepcionNotificacionModoPrueba();
        }else{
            destinatario = (rs.getCliente().getDireml()==null?"":rs.getCliente().getDireml());
        }

        
        if(!destinatario.isEmpty()){

            ce.setDestinatarios(destinatario);
            ce.setAsunto(rs.getPool().getTipo().getDescrp()+" "+rs.getNroPool() + " No se ha Activado! - Su reserva queda sin efecto");
            List<String> contenido = new ArrayList<String>();

            contenido.add("<b>Estimado cliente:<b/>");
            contenido.add("Cumplimos en informarle que su reserva en "+rs.getPool().getTipo().getDescrp()+" "+rs.getNroPool()+ " ha quedado sin efecto.");
            contenido.add("No se cumplieron las condiciones necesarias para activar la venta especial");

            contenido.add("<hr/>");
            contenido.add("<b>Detalle</b>");
            contenido.add("<hr/>");
            contenido.add("Nro: " + rs.getPool().getNroPool());
            contenido.add("Descripción: " + rs.getPool().getDescripcion());
            contenido.add("Disponible desde: " + formateadorFechaHora.format(rs.getPool().getDisponibleDesde()));
            contenido.add("Disponible hasta: " + formateadorFechaHora.format(rs.getPool().getDisponibleHasta()));
            contenido.add("Cantidad publicada:" + rs.getPool().getCantidadTotal().toBigInteger());
            contenido.add("Cantidad disponible:" + rs.getPool().getCantidadDisponible().toBigInteger());

            UtilidadesPool.agregarBasesCondiciones(rs.getPool(), contenido);

            ce.setContenido(mailFactoryBean.generarMensaje("Ventas especiales",contenido));

        }else{

            destinatario = (rs.getCliente().getSitio().getEmailPedidos()==null?"":rs.getCliente().getSitio().getEmailPedidos());
            if(destinatario.isEmpty()){
                destinatario = "claudiotrosch@gmail.com";
            }

            ce = JsfUtil.getCorreoElectronicoClienteSinCorreo(rs.getCliente(), destinatario);  
        }
        return ce;
    }

    public void enviarNotificaciones(){

        //Enviamos los correos con un nuevo hilo...
        SenderEmail se = new SenderEmail(mailFactoryBean, correos);
        se.start();
    }

    public CorreoElectronico generarCorreoResumenPoolEmpresa(Pool pool){

        String asunto = pool.getTipo().getDescrp() + " - Nro.: " + pool.getNroPool() + " - " + pool.getDescripcion() + " No Activada!";
        String destinatarios;
        
        try {
            destinatarios = parametroRN.getParametros().getCorreoElectronicoPool();
        } catch (Exception ex) {
            destinatarios = "claudiotrosch@gmail.com";
        }

        SimpleDateFormat formateadorFecha = new SimpleDateFormat("dd/MM/yyyy");
        SimpleDateFormat formateadorFechaHora = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

        List<String> contenido = new ArrayList<String>();

        contenido.add("<b>Venta especial finalizada sin éxito</b>");
        contenido.add("No se han cumplido las condiciones necesarias.");
        contenido.add("<hr/>");
        contenido.add("Nro: " + pool.getNroPool());
        contenido.add("Descripción: " + pool.getDescripcion());
        contenido.add("Disponible desde: " + formateadorFechaHora.format(pool.getDisponibleDesde()));
        contenido.add("Disponible hasta: " + formateadorFechaHora.format(pool.getDisponibleHasta()));
        contenido.add("Cantidad publicada:" + pool.getCantidadTotal().toBigInteger());
        contenido.add("Cantidad disponible:" + pool.getCantidadDisponible().toBigInteger());

        contenido.add("<b>Reservas confirmadas</b>");
        contenido.add("<hr/>");

        for (ReservasPool rs : pool.getReservas()) {

            contenido.add( "(" + rs.getCliente().getNrocta() + ") " + rs.getCliente().getNombre());
        }

        CorreoElectronico cee = new CorreoElectronico(asunto, destinatarios, mailFactoryBean.generarMensaje("Ventas especiales",contenido));

        return cee;
    }

    public String getStringFechaServer(){

        String s ="";
        Calendar f = Calendar.getInstance();
        f.setTime(new Date());

        s = s + String.valueOf(f.get(Calendar.YEAR)) + ",";
        s = s + String.valueOf(f.get(Calendar.MONTH)) + ",";
        s = s + String.valueOf(f.get(Calendar.DAY_OF_MONTH)) + ",";

        if(f.get(Calendar.AM_PM)==Calendar.AM){
            s = s + String.valueOf(f.get(Calendar.HOUR)) + ",";
        }else{
            s = s + String.valueOf(12+f.get(Calendar.HOUR)) + ",";
        }

        s = s + String.valueOf(f.get(Calendar.MINUTE)) + ",";
        s = s + String.valueOf(f.get(Calendar.SECOND)) ;
        return s;
    }
    
    /**
     * Metodo para obtener un string de la fecha de fin para el pool de venta
     * sin este string la funcion javascrip no funciona
     * @return
     */
    
    public String fechaFin(Pool p){

        try {
            String s = "";
            Calendar f = Calendar.getInstance();
            f.setTime(p.getDisponibleHasta());

            s = s + String.valueOf(f.get(Calendar.YEAR)) + ",";
            s = s + String.valueOf(f.get(Calendar.MONTH)) + ",";
            s = s + String.valueOf(f.get(Calendar.DAY_OF_MONTH)) + ",";

            if (f.get(Calendar.AM_PM) == Calendar.AM) {
                s = s + String.valueOf(f.get(Calendar.HOUR)) + ",";
            } else {
                s = s + String.valueOf(12 + f.get(Calendar.HOUR)) + ",";
            }

            s = s + String.valueOf(f.get(Calendar.MINUTE)) + ",";
            s = s + String.valueOf(f.get(Calendar.SECOND));
            return s;
        } catch (Exception e) {
            return "";
        }
    }

    public List<Pool> getPooles() {
        return pooles;
    }

    public void setPooles(List<Pool> pooles) {
        this.pooles = pooles;
    }

    public Parametro getP() {
        return p;
    }

    public void setP(Parametro p) {
        this.p = p;
    }

    public List<Pool> getPoolesRestringidos() {
        return poolesRestringidos;
    }

    public void setPoolesRestringidos(List<Pool> poolesRestringidos) {
        this.poolesRestringidos = poolesRestringidos;
    }

}
